package com.stone.framework.user.service.impl;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stone.framework.core.exception.BusinessException;
import com.stone.framework.core.util.Beans;
import com.stone.framework.core.util.Strings;
import com.stone.framework.message.user.RolePageReqBody;
import com.stone.framework.message.user.RolePageResBody;
import com.stone.framework.message.user.RoleReqBody;
import com.stone.framework.user.entity.Role;
import com.stone.framework.user.entity.RoleResource;
import com.stone.framework.user.entity.RoleUser;
import com.stone.framework.user.mapper.PermissionMapper;
import com.stone.framework.user.mapper.RoleMapper;
import com.stone.framework.user.mapper.RoleUserMapper;
import com.stone.framework.user.service.RoleService;

@Service
@Transactional(readOnly = true)
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private RoleUserMapper roleUserMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    @Override
    public IPage<RolePageResBody> queryPage(RolePageReqBody reqBody, Page<Role> page) {
        Role entity = new Role();
        Beans.copyProperties(reqBody, entity);
        return roleMapper.selectPage(page, this.condition(entity)).convert(e -> {
            RolePageResBody resBody = new RolePageResBody();
            Beans.copyProperties(e, resBody);
            return resBody;
        });
    }

    @Override
    public Map<String, String> query() {
        Role condition = new Role();
        condition.setState("ENABLED");
        List<Role> list = roleMapper.selectList(this.condition(condition));
        return list.stream().collect(Collectors.toMap(Role::getCode, Role::getName, (u, v) -> u));
    }

    @Override
    public List<String> queryByUsername(String username) {
        return roleMapper.selectByUsername(username);
    }

    @Override
    @Transactional(readOnly = false)
    public void save(RoleReqBody reqBody) {
        Role entity = new Role();
        Beans.copyProperties(reqBody, entity);
        Integer count = roleMapper.selectCount(new QueryWrapper<Role>().eq("code", entity.getCode()));
        if (count > 0) {
            throw new BusinessException("角色已存在，请重新输入");
        }
        roleMapper.insert(entity);
    }

    @Override
    @Transactional(readOnly = false)
    public void modify(RoleReqBody reqBody) {
        Role entity = roleMapper.selectById(reqBody.getId());
        if (entity == null) {
            throw new BusinessException("角色不存在");
        }

        Beans.copyProperties(reqBody, entity);
        Integer count = roleMapper.selectCount(new QueryWrapper<Role>().eq("code", entity.getCode()));
        if (count > 1) {
            throw new BusinessException("角色代码重复，请重新输入");
        }
        roleMapper.updateById(entity);
    }

    @Override
    @Transactional(readOnly = false)
    public void delete(Long id) {

        Role entity = roleMapper.selectById(id);
        if (entity == null) {
            throw new BusinessException("角色不存在");
        }
        Integer count = roleUserMapper.selectCount(new QueryWrapper<RoleUser>().eq("role_id", id));
        if (count > 0) {
            throw new BusinessException("存在关联用户，请删除后再试");
        }
        roleMapper.deleteById(id);
        permissionMapper.delete(new QueryWrapper<RoleResource>().eq("role_id", id));
    }

    private QueryWrapper<Role> condition(Role condition) {
        QueryWrapper<Role> wrapper = new QueryWrapper<>();
        wrapper.like(Strings.notEmpty(condition.getCode()), "code", condition.getCode());
        wrapper.like(Strings.notEmpty(condition.getName()), "name", condition.getName());
        wrapper.like(Strings.notEmpty(condition.getDesc()), "desc_", condition.getDesc());
        wrapper.eq(Objects.nonNull(condition.getState()), "state", condition.getState());
        return wrapper;
    }

}
